<?php
/**
 * Eren Framework
 * 
 * File Operation class
 * 
 * @category System
 * @author Manu Soros Leu
 * @copyright manusoros@gmail.com
 */

class Eren_File
{    
    /**
     * write content to a file
     * 
     * @param string $fileName
     * @param string $content
     * @param bool $lock
     * @throws Eren_Exception
     * 
     * @return int
     */
    public static function write($fileName, $content, $lock = TRUE)
    {
        if(is_array($fileName) || $fileName == NULL || is_array($content) || $content == NULL){
            throw new Eren_Exception('The params of Eren_File::write must be string and cant be NULL');
        }
        if(!($fp = fopen($fileName, 'wb'))){
            throw new Eren_Exception("The file '{$fileName}' open failed!!");
        }
        if($lock && !flock($fp, LOCK_EX)){
            fclose($fp); 
            throw new Eren_Exception("The file '{$fileName}' lock failed!!");
        }
        if(!($ret = fwrite($fp, $content))){
            fclose($fp); 
            throw new Eren_Exception("The file '{$fileName}' write failed!!");
        }
        if($lock){
            flock($fp, LOCK_UN);    
        }
        fclose($fp);
        return $ret;
    } 
    
    /**
     * append content to a file
     * 
     * @param string $fileName
     * @param string $content
     * @param bool $lock
     * @throws Eren_Exception
     * 
     * @return int
     */
    public static function append($fileName, $content, $lock = FALSE)
    {
        if(is_array($fileName) || $fileName == NULL || is_array($content) || $content == NULL){
            throw new Eren_Exception('The params of Eren_File::append must be string and cant be NULL');
        }
        if(!($fp = fopen($fileName, 'ab'))){
            throw new Eren_Exception("The file '{$fileName}' open failed!!");
        }
        if($lock && !flock($fp, LOCK_EX)){
            fclose($fp);
            throw new Eren_Exception("The file '{$fileName}' lock failed!!");
        }
        if(!($ret = fwrite($fp, $content))){
            fclose($fp);
            throw new Eren_Exception("The file '{$fileName}' append failed!!");
        }
        if($lock){
            flock($fp, LOCK_UN);    
        }
        fclose($fp);
        return $ret;
    } 
    
    /**
     * Read content from file
     * 
     * @param string $fileName
     * @param int $length
     * @param int $start
     * @param bool $lock
     * @throws Eren_Exception
     * 
     * @return string
     */
    public static function read($fileName, $length, $start = 0, $lock = TRUE)
    {
        if(is_array($fileName) || $fileName == NULL){
            throw new Eren_Exception('The params of Eren_File::readAll must be string and cant be NULL');
        }
        if(!is_numeric($length) || $length <= 0){
            throw new Eren_Exception("The first param of length must be int and >=0");
        }
        $start = intval($start);
        if(!($fp = fopen($fileName, 'rb'))){
            throw new Eren_Exception("The file '{$fileName}' open failed!!");
        }
        if($lock && !flock($fp, LOCK_SH)){
            fclose($fp); 
            throw new Eren_Exception("The file '{$fileName}' lock failed!!");
        }
        fseek($fp,$start);
        $ret = fread($fp, $length);
        if($lock){
            flock($fp, LOCK_UN);    
        }
        fclose($fp);
        return $ret;
    }
    
    /**
     * Read all content from file
     * 
     * @param string $fileName
     * @param bool $lock
     * @throws Eren_Exception
     * 
     * @return string
     */
    public static function readAll($fileName, $lock = TRUE)
    {
        if(is_array($fileName) || $fileName == NULL){
            throw new Eren_Exception('The params of Eren_File::readAll must be string and cant be NULL');
        }
        if(!($fp = fopen($fileName, 'rb'))){
            throw new Eren_Exception("The file '{$fileName}' open failed!!");
        }
        if($lock && !flock($fp, LOCK_SH)){
            fclose($fp);
            throw new Eren_Exception("The file '{$fileName}' lock failed!!");
        }
        $ret = file_get_contents($fileName);
        if($lock){
            flock($fp, LOCK_UN);
        }
        fclose($fp);
        return $ret;
    }
    
    /**
     * Read all content from one file to another
     * 
     * @param string $fileName
     * @param string $tgtFileName
     * @throws Eren_Exception
     * 
     * @return void
     */
    public static function readFileToFile($fileName, $tgtFileName)
    {
        if(is_array($fileName) || $fileName == NULL){
            throw new Eren_Exception('The first param of Eren_File::readFileToFile must be string and cant be NULL');
        }
        if(is_array($tgtFileName) || $tgtFileName == NULL){
            throw new Eren_Exception('The second param of Eren_File::readFileToFile must be string and cant be NULL');
        }
        if(!($fp = fopen($fileName, 'rb'))){
            throw new Eren_Exception("The file '{$fileName}' open failed!!");
        }
        if(!($tfp = fopen($tgtFileName, 'ab'))){
            throw new Eren_Exception("The file '{$tgtFileName}' open failed!!");
        }
        while(!feof($fp)){
            if(($word = trim(fgets($fp), "\r\n\t ")) == ""){
                continue;
            }
            fwrite($tfp, $word . "\n");
        }
        fclose($fp);
        fclose($tfp);
    }
    
    /**
     * Delete a file
     * 
     * @param string $fileName
     * @throws Eren_Exception
     * 
     * @return bool
     */
    public static function delete($fileName)
    {
        if(file_exists($fileName)){
            if(!is_file($fileName)){
                throw new Eren_Exception("The '{$fileName}' is not a File!!");
            }
            return @unlink($fileName);
        }
        return TRUE;
    }
    
    /**
     * Delete a forder 
     *
     * @param string $forderName
     * 
     * @return bool
     */
    public static function deleteALL($forderName)
    {
        if(!file_exists($forderName)){
            return true;    
        }
        if(!is_dir($forderName)){
            return self::delete($forderName);
        }    
        $dh=opendir($forderName);
        while($file=readdir($dh)){
            if($file=="." || $file==".."){
                continue;
            }
            $fullDir = $forderName . '/' . $file;
            if(is_dir($fullDir)){
                self::deleteALL($fullDir);
            }
            else{
                self::delete($fullDir);
            }
        }
        closedir($dh);
        return rmdir($forderName);
    }
    
    /**
     * Get the info of File
     * 
     * @param string $fileName
     * @throws Eren_Exception
     * 
     * @return array
     */
    public static function info($fileName)
    {
        if(!file_exists($fileName) || is_dir($fileName)){
            throw new Eren_Exception("The {$fileName} is not exist or is not a file");
        }
        $ret = array();
        $ret['size'] = filesize($fileName);
        $ret['modify'] = filemtime($fileName);
        $ret['visite'] = fileatime($fileName);
        return $ret;
    }
    
    /**
     * Is Dir
     * 
     * @param string $forder
     * @throws Eren_Exception
     * 
     * @return bool
     */
    public static function isDir($forder)
    {
        if($forder==NULL || !is_string($forder)){
            throw new Eren_Exception("The param must be string and cant be NULL");
        }
        
        if(is_dir($forder)){
            return TRUE;
        }
        
        return FALSE;
    }
    
    /**
     * Is exist
     * 
     * @param string $file
     * @throws Eren_Exception
     * 
     * @return bool
     */
    public static function isExist($file)
    {
        if($file==NULL || !is_string($file)){
            throw new Eren_Exception("The param must be string and cant be NULL");
        }
        
        if(file_exists($file)){
            return TRUE;
        }
        
        return FALSE;
    }
    
    /**
     * get all line as key to array
     * 
     * @param string $file
     * @throws Eren_Exception
     * 
     * @return array
     */
    public static function allLineToArr($file)
    {
        if($file==NULL || !is_string($file)){
            throw new Eren_Exception("The param must be string and cant be NULL");
        }
        
        $arr = array();
        if(!Eren_File::isExist($file)){
            return $arr;
        }
    
        if(($handle = fopen($file, "r")) == false){
           throw new Eren_Exception("Open [{$file}] error");
        }
        
        while(!feof($handle)){
            $line = fgets($handle);
            $line = trim($line, "\r\n\t ");
            if($line == "") continue;
            $arr[$line] = 1;
        }
        
        fclose($handle);
        
        return $arr;
    }
}